package model

import (
	"gopkg.in/mgo.v2/bson"
	"src/config"
	newtime "src/util/time"
)

type Message struct {
	Id        bson.ObjectId `bson:"_id,omitempty" json:"id,omitempty"`
	Status    int           `bson:"status" json:"status"`
	Anonymity bool          `bson:"anonymity" json:"anonymity"`

	Type            int    `bson:"type" json:"type"`
	ForumPostId     string `bson:"forum_post_id" json:"forum_post_id"`
	ActionUserId    string `bson:"action_user_id" json:"action_user_id"`
	ActionContentId string `bson:"action_content_id" json:"action_content_id"`
	UserID          string `bson:"user_id" json:"user_id"`
	ContentId       string `bson:"content_id" json:"content_id"`

	IssueTime int64 `bson:"issue_time" json:"issue_time"`
	ReadTime  int64 `bson:"read_time" json:"read_time"`
}

func CreatMessage(m Message) error {
	query := bson.M{
		"type":              m.Type,
		"action_user_id":    m.ActionUserId,
		"action_content_id": m.ActionContentId,
		"user_id":           m.UserID,
		"content_id":        m.ContentId,
	}
	_, err := findMessage(query, DefaultSelector)
	if err == nil {
		return nil
	}
	m.IssueTime = newtime.GetMilliTimestamp()
	m.Status = config.MessageNewStatus
	return insertMessage(m)
}

func DeleteMessage(m Message) error {
	var query bson.M
	if m.Type != 12 && m.Type != 15 {
		query = bson.M{
			"type":              m.Type,
			"action_user_id":    m.ActionUserId,
			"action_content_id": m.ActionContentId,
			"content_id":        m.ContentId,
		}
	} else {
		query = bson.M{
			"type":           m.Type,
			"action_user_id": m.ActionUserId,
			"content_id":     m.ContentId,
		}
	}
	m, err := findMessage(query, DefaultSelector)
	if err != nil {
		return nil
	}
	return deleteMessage(m.Id)
}

//func DeleteMessageAll(query interface{}) error {
//	field := []string{
//		"-issue_time",
//	}
//	messages,_ := findMessagesALL(query,field...)
//	for i := 0;i<len(messages);i++ {
//		deleteMessage(messages[i].Id)
//	}
//	return nil
//}

func GetMessage(user_id string, page, perpage int) ([]Message, error) {
	query := bson.M{
		"user_id": user_id,
	}
	fields := []string{
		"-issue_time",
	}
	return findMessages(query, DefaultSelector, page, perpage, fields...)
}

func ReadMessage(userid string) error {
	query := bson.M{
		"user_id": userid,
		"status":  config.MessageNewStatus,
	}
	messages, err := findMessagesALL(query)
	if err != nil {
		return err
	}

	update := bson.M{
		"$set": bson.M{
			"status":    config.MessageReadStatus,
			"read_time": newtime.GetMilliTimestamp(),
		},
	}
	for i := 0; i < len(messages); i++ {
		query := bson.M{
			"_id":     messages[i].Id,
			"user_id": userid,
		}
		_ = updateMessage(query, update)
	}
	return updateMessage(query, update)
}

/******************************************************/
func updateMessage(query, update interface{}) error {
	sess := globalSess.Clone()
	defer sess.Close()
	messageTable := sess.DB(DBNAME).C(MESSAGETABLE)

	return messageTable.Update(query, update)
}
func deleteMessage(id bson.ObjectId) error {
	sess := globalSess.Clone()
	defer sess.Clone()
	messageTable := sess.DB(DBNAME).C(MESSAGETABLE)
	return messageTable.RemoveId(id)

}

func insertMessage(docs ...interface{}) error {
	sess := globalSess.Clone()
	defer sess.Close()
	messageTable := sess.DB(DBNAME).C(MESSAGETABLE)

	return messageTable.Insert(docs...)
}
func findMessage(query, selector interface{}) (Message, error) {
	sess := globalSess.Copy()
	defer sess.Close()
	messageTable := sess.DB(DBNAME).C(MESSAGETABLE)

	message := Message{}
	err := messageTable.Find(query).Select(selector).One(&message)
	return message, err
}
func findMessageNum(query interface{}) (int, error) {
	sess := globalSess.Copy()
	defer sess.Close()
	messageTable := sess.DB(DBNAME).C(MESSAGETABLE)

	return messageTable.Find(query).Count()
}
func findMessages(query, selector interface{}, page, perPage int, fields ...string) ([]Message, error) {
	sess := globalSess.Copy()
	defer sess.Close()
	messageTable := sess.DB(DBNAME).C(MESSAGETABLE)

	messages := []Message{}
	err := messageTable.Find(query).Select(selector).Sort(fields...).Skip((page - 1) * perPage).Limit(perPage).All(&messages)
	return messages, err
}
func findMessagesALL(query interface{}, fields ...string) ([]Message, error) {
	sess := globalSess.Copy()
	defer sess.Close()
	messageTable := sess.DB(DBNAME).C(MESSAGETABLE)

	messages := []Message{}
	err := messageTable.Find(query).Sort(fields...).All(&messages)
	return messages, err
}
